package com.nulldev.util.concurrency.threadIt.v4.emapi;

import java.util.ArrayList;
import java.util.List;

import com.nulldev.util.concurrency.threadIt.v3.extensions.TaskStatus;
import com.nulldev.util.concurrency.threadIt.v4.emapi.ft.FutureTask;
import com.nulldev.util.concurrency.threadIt.v4.emapi.uft.Executable;
import com.nulldev.util.concurrency.threadIt.v4.emapi.uft.Returnable;
import com.nulldev.util.data.Variables;
import com.nulldev.util.internal.backport.concurrency9.Lists;

public class Tasks {

	public static Object[] all(final Executable<?>... tasks) {
		if (tasks == null || tasks.length == 0)
			return new Object[0];
		final Object[] out = new Object[tasks.length];
		ExecutorManager.get().await(tasks);
		for (int i = 0; i < tasks.length; i++)
			out[i] = tasks[i].result();
		return out;
	}

	public static List<Object> _all(final Executable<?>... tasks) {
		if (tasks == null || tasks.length == 0)
			return Lists.of();
		final List<Object> out = new ArrayList<Object>(tasks.length);
		ExecutorManager.get().await(tasks);
		for (int i = 0; i < tasks.length; i++)
			out.set(i, tasks[i].result());
		return out;
	}

	public static <T> Executable<T> fail(final Throwable err) {
		Variables.requireNonNull(err, "err");
		return new FutureTask<T>() {

			@Override
			public T execute() {
				throw new RuntimeException(err);
			}
		};
	}

	public static <T> Executable<T> resolve(final T item) {
		final Executable<T> resolved = new FutureTask<T>() {

			@Override
			public T execute() {
				return item;
			}
		};
		resolved.run_st();
		return resolved;
	}

	// TODO: Check with the Tasks spec if this function should exist at all.
	public static <T> Executable<T> fail(final Executable<T> err) {
		Variables.requireNonNull(err, "err");
		if (!err.requestCancel())
			err.kill();
		return err;
	}

	public static <T> Executable<T> rejected(final Returnable<T> r) {
		Variables.requireNonNull(r, "r");
		return FutureTask.dummy(TaskStatus.SUBMISSION_FAILED);
	}

}
